/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
/* Copyright (C) 2012 Zongyou Yao. All rights reserved.     */

#ifndef THREAD_INCLUDED
#define THREAD_INCLUDED

#include "except.h"

/**
 * It is a checked runtime error to call any thread function before calling thread_init.
 */
typedef struct thread_t * thread_t;

extern const except_t thread_failed;
extern const except_t thread_alerted;

/**
 * Initializes the thread for nonpreemptivve (preempt = 0) or preemptive (preempt = 1)
 * scheduling and returns preempt or zero if preempt = 1 and preemptive scheduling is not
 * supported. Thread_init may accept additional implementation-defined parameters; the 
 * argument list must be terminated with a null. It is a checked runtime error to call
 * thread_init more than once.
 */
int thread_init(int preempt, ...);

/**
 * Creates, initializes, and starts a new thread, and returns its handle. If 
 * nbytes == 0, the new thread executes thread_exit(apply(args)); otherwise, 
 * it executes thread_exit(apply(p)), where p points to a copy of the nbytes 
 * block starting at args. The new thread starts with its own empty exception
 * stack. thread_new may accept additional implementation-defined parameters; 
 * the argument list must be terminated with a null. It is a checked runtime 
 * error for apply == null, or for args == null and nbytes < 0.
 * Exception thread_failed can be raised.
 */
thread_t thread_new(int apply(void *), void *args, int nbytes, ...);

/**
 * Terminates the calling thread and passes code to any threads waiting for the calling
 * thread to terminate. Where the last thread calls thread_exit, the program terminates
 * with exit(code).
 */
void thread_exit(int code);

/**
 * Sets thread's alert-pending flag and makes t runnable. The next time thread runs,
 * or calls a blocking thread, sem, or chan primitive, it clears its flag and raises
 * thread_alerted. It is a checked runtime error for t == null or to name a nonexistent
 * thread.
 */
void thread_alert(thread_t thread);

/**
 * Returns the calling thread's handle.
 */
thread_t thread_self(void);

/**
 * Suspends the calling thread until thread thread terminates. When thread terminates,
 * thread_join returns thread's exit code. If t == null, the calling thread waits for
 * all other threads to terminate, and then returns zero. It is a checked runtime error
 * for thread to name the calling thread or for more than one thread to pass a null thread.
 * Exception thread_alerted can be raised.
 */
int thread_join(thread_t thread);

/**
 * Relinquishes the processor to another thread, perhaps the caller.
 */
void thread_pause(void);

#endif
